#ifndef RTTIMERQUEUEBASE_H
#define RTTIMERQUEUEBASE_H

#include "RtMutex.h"
#include "RtTimeValue.h"
#include "RtThreadInterface.h"

class IRtObserver;

class /*RT_API_EXPORT*/ CRtTimerQueueBase : public IRtTimerQueue
{
public:
	struct CNode
	{
		CNode(IRtTimerHandler *aEh = NULL, LPVOID aToken = NULL) 
			: m_pEh(aEh), m_pToken(aToken), m_dwCount(0) 
		{ }

		IRtTimerHandler *m_pEh;
		LPVOID m_pToken;
		CRtTimeValue m_tvExpired;
		CRtTimeValue m_tvInterval;
		DWORD m_dwCount;
	};
	
	CRtTimerQueueBase(IRtObserver *aObserver);
	virtual ~CRtTimerQueueBase();


	virtual RtResult ScheduleTimer(IRtTimerHandler *aEh, 
					  LPVOID aToken, 
					  const CRtTimeValue &aInterval,
					  DWORD aCount);

	virtual RtResult CancelTimer(IRtTimerHandler *aEh);
	/// if the queue is empty, return CRtTimeValue::s_tvMax.
	CRtTimeValue GetEarliestTime();

	/// return the number of timer expired.
	/// and fill <aRemainTime> with the sub-value of earliest time and current time,
	/// if no timer items in the queue, fill <aRemainTime> with <CRtTimeValue::s_tvMax>.
	int CheckExpire(CRtTimeValue *aRemainTime = NULL);

protected:
	/// the sub-classes of CRtTimerQueueBase always use STL contains that 
	/// we just let them manage the memery allocation of CNode
	
	/// the following motheds are all called after locked
	virtual int PushNode_l(const CNode &aPushNode) = 0;
	virtual int EraseNode_l(IRtTimerHandler *aEh) = 0;
	virtual int RePushNode_l(const CNode &aPushNode) = 0;
	virtual int PopFirstNode_l(CNode &aPopNode) = 0;
	virtual int GetEarliestTime_l(CRtTimeValue &aEarliest) const = 0;

	typedef CRtMutexNullSingleThread MutexType;
	MutexType m_Mutex;
	IRtObserver *m_pObserver;
	CRtTimeValue m_tick;
};

#endif // !RTTIMERQUEUEBASE_H
